import './assets/scss/index.scss';
import Graphic from './graphic/graphic';
import './geo/math';
import { FeatureType } from './types';
import Feature from './feature/feature';
import Vertex from './feature/vertex';
import { getAnotation } from './util/util';

export default (option: any) => {
    const { map } = option;

    if (!map) {
        throw new Error("Parameter 'map' is required!");
    }

    // 初始化图形类
    const graphic = new Graphic(map);

    /**
     * 展示history中保存的数据
     */
    function show() {
        graphic.showCacheFeature();
    }

    /**
     * 清除地图上要素，不清理history
     */
    function clear() {
        graphic.removeAllFeature();
    }

    /**
     * 清除history数据
     */
    function clearCache() {
        graphic.history.clear();
    }

    /**
     * 渲染视野范围内的要素
     * @param features<{latLngs,type,id}[]>
     */
    function render(params: any): Feature[] | undefined {
        if (!Array.isArray(params)) {
            return;
        }
        // 把latLngs对象 包装成 latLngs 数组
        const points = params
            .filter((item) => {
                return item.type === 'point';
            })
            .map((item) => {
                item.latLngs = [item.latLngs];
                return item;
            });
        graphic.layers['point'].render(points);
        const lines = params.filter((item) => {
            return item.type === 'line';
        });
        graphic.layers['line'].render(lines);

        const polygons = params.filter((item) => {
            return item.type === 'polygon';
        });
        graphic.layers['polygon'].render(polygons);

        // const features = points.concat(linesOrPolygons);
        // graphic.render(features);
    }

    function draw(type: FeatureType) {
        graphic.draw(type);
    }

    // click <FeatureJson,MouseEvent>
    // dragEnd  <FeatureJson,LeafletMouseEvent>
    function on(type: string, fn: Function) {
        return graphic.eventBus.on(type, fn);
    }

    function off(type: string, fn: Function) {
        return graphic.eventBus.off(type, fn);
    }

    /**
     * 撤销
     */
    function undo() {
        return graphic.history.undo();
    }

    /**
     * 重做
     */
    function redo() {
        return graphic.history.redo();
    }

    /**
     * 点线面删除方法
     * @param type 要素类型 <'polygon' | 'line' | 'point' | 'node'>
     * @param id 要素id
     * @returns
     */
    function remove(id: string): Promise<any> {
        return new Promise((resolve, reject) => {
            const allFeatures = graphic.getAllFeatures();
            const feature = allFeatures.get(id);
            if (!feature) {
                reject({ status: 500, message: '未找到此要素' });
                return;
            }
            // 删除顶点，保存顶点关联要素
            const features = feature.type === 'node' ? (feature as Vertex).relateFeatures : [feature];
            // 删除前，如果history不包含此要素，先添加一下要素
            graphic.addHistory({ annotation: getAnotation('add base '), features }, true);
            // latLngs 清空后再存入history
            const del = graphic.removeFeature(feature.type, id);

            if (del) {
                graphic.addHistory({
                    annotation: getAnotation('remove ', feature),
                    features,
                });
                resolve({ status: 200, message: '删除成功' });
            } else {
                reject({ status: 500, message: '删除失败' });
            }
        });
    }

    /**
     * 要素定位
     * @param id 要素id
     * @returns
     */
    function fitFeature(id: string) {
        return new Promise((resolve, reject) => {
            const allFeatures = graphic.getAllActualFeatures();
            const feature = allFeatures.get(id);
            if (!feature) {
                reject({ status: 500, message: '未找到此要素' });
                return;
            }
            const res = graphic.fitFeature(feature.type, id);
            if (res) {
                resolve({ status: 200, message: '定位成功' });
            } else {
                reject({ status: 500, message: '定位失败' });
            }
        });
    }

    /**
     * 高亮要素（不定位）
     * @param id
     * @returns
     */
    function activeFeature(id: string) {
        const allFeatures = graphic.getAllActualFeatures();
        const feature = allFeatures.get(id);
        if (!feature) {
            throw new Error('未找到此要素');
        }
        graphic.changeMode('select', feature);
    }

    /**
     * #TODO 返回类型
     * 获取需要保存的要素信息
     * @returns
     */
    function getUnSavedFeatures(): any {
        return graphic.history.getUnSavedFeatures();
    }

    /**
     * 获取所有的要素
     * @returns Feature[]
     */
    function getAllActualFeatures(): Feature[] {
        return Array.from(graphic.getAllActualFeatures().values());
    }

    /**
     * 获取选中要素
     * @returns
     */
    function getHighlightFeature(): Feature | undefined | null {
        return graphic.mode.selectedFeature;
    }

    /**
     * 根据id获取要素
     * @param id
     * @returns 要素实例化对象或者undefined
     */
    function getFeature(id: string) {
        const allFeatures = graphic.getAllFeatures();
        const feature = allFeatures.get(id);
        return feature?.instance();
    }

    /**
     * 批量更新要素id
     * @param params {[oldId:string]:newId}
     */
    function batchChangeId(params: { [key: string]: string }): void {
        Object.keys(params).forEach((key) => {
            graphic.changeFeatureId(key, params[key]);
        });
    }

    return {
        show,
        clear,
        clearCache,
        render,
        draw,
        on,
        off,
        undo,
        redo,
        remove,
        getUnSavedFeatures,
        getAllActualFeatures,
        getHighlightFeature,
        getFeature,
        fitFeature,
        activeFeature,
        batchChangeId,
    };
};
